/*
dead6309 version 1.00

started janurary 2008

copyright 2008 Dead_Body

note: uses files in Dead6809, you must have it to use this core
*/

#include "StdAfx.h"
#include "Dead6309.h"

#define F_CARRY		0x01
#define F_OVERFLOW	0x02
#define F_ZERO			0x04
#define F_NEGATIVE	0x08
#define F_IRQ			0x10
#define F_HALFCARRY	0x20
#define F_FIRQ			0x40

#define F_MD_EM		0x01		// Execution mode
#define F_MD_FM		0x02		// FIRQ mode
#define F_MD_II		0x40		// Illegal instruction
#define F_MD_DZ		0x80		// Division by zero

#define A acc.b.A
#define B acc.b.B
#define D acc.D

#define E w.b.E
#define F w.b.F
#define W w.W

static int INT_NMI = 1;
static int INT_IRQ = 2;
static int INT_FIRQ = 4;

static unsigned char c6309Cycles[256] =
{
6,6,6,6,6,6,6,6,6,6,6,6,6,6,3,6,
0,0,2,4,0,0,5,9,0,2,3,0,3,2,8,6,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,5,5,5,5,0,5,3,6,9,11,0,19,
2,0,0,2,2,0,2,2,2,2,2,0,2,2,0,2,
2,0,0,2,2,0,2,2,2,2,2,0,2,2,0,2,
6,0,0,6,6,0,6,6,6,6,6,0,6,6,3,6,
7,0,0,7,7,0,7,7,7,7,7,0,7,7,4,7,
2,2,2,4,2,2,2,0,2,2,2,2,4,7,3,0,
4,4,4,6,4,4,4,4,4,4,4,4,6,7,5,5,
4,4,4,6,4,4,4,4,4,4,4,4,6,7,5,5,
5,5,5,7,5,5,5,5,5,5,5,5,7,8,6,6,
2,2,2,4,2,2,2,0,2,2,2,2,3,0,3,0,
4,4,4,6,4,4,4,4,4,4,4,4,5,5,5,5,
4,4,4,6,4,4,4,4,4,4,4,4,5,5,5,5,
5,5,5,7,5,5,5,5,5,5,5,5,6,6,6,6
};

static char *OpcodeTable[256] =
{
"NEG ","OIM ","AIM ","COM ","LSR ","EIM ","ROR ","ASR ","ASL ","ROL ","DEC ","TIM ","INC ","TST ","JMP ","CLR ",
"--  ","--  ","NOP ","SYNC","??  ","??  ","LBRA","LBSR","??  ","DAA ","ORCC","??  ","ANDC","SEX ","EXG ","TFR ",
"BRA ","BRN ","BHI ","BLS ","BCC ","BLO ","BNE ","BEQ ","BVC ","BVS ","BPL ","BMI ","BGE ","BLT ","BGT ","BLE ",
"LEAX","LEAY","LEAS","LEAU","PSHS","PULS","PSHU","PULU","??  ","RTS ","ABX ","RTI ","CWAI","MUL ","??  ","SWI ",
"NEGA","??  ","??  ","COMA","LSRA","??  ","RORA","ASRA","ASLA","ROLA","DECA","??  ","INCA","TSTA","??  ","CLRA",
"NEGB","??  ","??  ","COMB","LSRB","??  ","RORB","ASRB","LSLB","ROLB","DECB","??  ","INCB","TSTB","??  ","CLRB",
"NEG ","??  ","??  ","COM ","LSR ","??  ","ROR ","ASR ","ASL ","ROL ","DEC ","??  ","INC ","TST ","JMP ","CLR ",
"NEG ","??  ","??  ","COM ","LSR ","??  ","ROR ","ASR ","ASL ","ROL ","DEC ","??  ","INC ","TST ","JMP ","CLR ",
"SUBA","CMPA","SBCA","SUBD","ANDA","BITA","LDA ","??  ","EORA","ADCA","ORA ","ADDA","CMPX","BSR ","LDX ","??  ",
"SUBA","CMPA","SBCA","SUBD","ANDA","BITA","LDA ","STA ","EORA","ADCA","ORA ","ADDA","CMPX","JSR ","LDX ","STX ",
"SUBA","CMPA","SBCA","SUBD","ANDA","BITA","LDA ","STA ","EORA","ADCA","ORA ","ADDA","CMPX","JSR ","LDX ","STX ",
"SUBA","CMPA","SBCA","SUBD","ANDA","BITA","LDA ","STA ","EORA","ADCA","ORA ","ADDA","CMPX","JSR ","LDX ","STX ",
"SUBB","CMPB","SBCB","ADDD","ANDB","BITB","LDB ","??  ","EORB","ADCB","ORB ","ADDB","LDD ","??  ","LDU ","??  ",
"SUBB","CMPB","SBCB","ADDD","ANDB","BITB","LDB ","STB ","EORB","ADCB","ORB ","ADDB","LDD ","STD ","LDU ","STU ",
"SUBB","CMPB","SBCB","ADDD","ANDB","BITB","LDB ","STB ","EORB","ADCB","ORB ","ADDB","LDD ","STD ","LDU ","STU ",
"SUBB","CMPB","SBCB","ADDD","ANDB","BITB","LDB ","STB ","EORB","ADCB","ORB ","ADDB","LDD ","STD ","LDU ","STU "
};

static char *OpcodeTableP1[256] =
{
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","LBRN","LBHI","LBLS","LBCC","LBCS","LBNE","LBEQ","LBVC","LBVS","LBPL","LBMI","LBGE","LBLT","LBGT","LBLE",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ",
"??  ","??  ","??  ","CMPD","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","CMPY","??  ","LDY ","??  ",
"??  ","??  ","??  ","CMPD","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","CMPY","??  ","LDY ","STY ",
"??  ","??  ","??  ","CMPD","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","CMPY","??  ","LDY ","STY ",
"??  ","??  ","??  ","CMPD","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","CMPY","??  ","LDY ","STY ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","LDS ","??  ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","LDS ","STS ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","LDS ","STS ",
"??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","??  ","LDS ","STS ",
};

CDead6309::CDead6309()
{
}

CDead6309::~CDead6309()
{
}

void CDead6309::Reset()
{
CDead6809::Reset();
V = 0;
W = 0;
MD = 0;
}

#include "Dead6309funcs.cpp"					//class members not found here
#include "Dead6309ops.cpp"						//opcodes used in Step()
#include "../dead6809/Dead6809ops.cpp"		//6809 opcodes

void CDead6309::Step()
{
u8 Opcode,Opcode2;							//current opcode
u8 tmp,ntmp,otmp;								//temp variables used by opcodes
u32 tmp2,tmp3;

CHECK_INTERRUPTS;
if(WaitInterrupt)
	{
	Cycle++;
	return;
	}
SavePC = PC;
Opcode = OpRead(PC++);
switch(Opcode)
	{
	#include "Dead6309switch.cpp"
	#define NO_PAGE
	#include "../dead6809/Dead6809switch.cpp"
	}
Cycle += c6309Cycles[Opcode];
}

void CDead6309::SaveState(CState *s)
{
CDead6809::SaveState(s);
}

void CDead6309::LoadState(CState *s)
{
CDead6809::LoadState(s);
}

//debugger
enum c6809addrmodes_e
	{
	c6809_addr_none = 0,
	c6809_addr_implied,
	c6809_addr_immediate,
	c6809_addr_immediate8,
	c6809_addr_direct,
	c6809_addr_indexed,
	c6809_addr_extended,
	c6809_addr_relative,
	c6809_addr_relative16
	};

static int GetAddrModeP1(u8 Opcode2)
{
switch(Opcode2 & 0xF0)
	{
	case 0x20:	return(c6809_addr_relative16);
	case 0x80:
	case 0xC0:	return(c6809_addr_immediate);
	case 0x90:
	case 0xD0:	return(c6809_addr_direct);
	case 0xA0:
	case 0xE0:	return(c6809_addr_indexed);
	case 0xB0:
	case 0xF0:	return(c6809_addr_extended);
	}
return(c6809_addr_immediate8);
}

static int GetAddrMode(u8 Opcode,u8 Opcode2)
{
switch(Opcode & 0xF0)
	{
	case 0x00:
		return(c6809_addr_direct);
	case 0x10:
		if(Opcode == 0x10)
			return(GetAddrModeP1(Opcode2));
		if(Opcode == 0x10)
			return(GetAddrModeP1(Opcode2));
		if(Opcode == 0x16 || Opcode == 0x17)
			return(c6809_addr_relative16);
		if(Opcode == 0x1E || Opcode == 0x1F)
			return(c6809_addr_immediate8);
		break;
	case 0x20:
		return(c6809_addr_relative);
	case 0x30:
		if(Opcode < 0x34)
			return(c6809_addr_indexed);
		else if(Opcode >= 0x34 && Opcode <= 0x37)
			return(c6809_addr_immediate8);
		else if(Opcode == 0x3C)
			return(c6809_addr_immediate8);
	case 0x40:
	case 0x50:
		return(c6809_addr_implied);
	case 0x60:
		return(c6809_addr_indexed);
	case 0x70:
		return(c6809_addr_extended);
	case 0x80:
		if(Opcode == 0x8D)		//bsr, relative
			return(c6809_addr_relative);
	case 0xC0:
		return(c6809_addr_immediate8);
	case 0x90:
	case 0xD0:
		return(c6809_addr_direct);
	case 0xA0:
	case 0xE0:
		return(c6809_addr_indexed);
	case 0xB0:
	case 0xF0:
		return(c6809_addr_extended);
	}
return(c6809_addr_none);
}

u32 CDead6309::Disassemble(char *dest,u32 p)
{
u8 Opcode,Opcode2,N,Reg;
char *Op;
char RegList[] = "XYUS";

Opcode = OpRead(p++);
Opcode2 = OpRead(p);
if(Opcode == 0x10)
	{
	Op = OpcodeTableP1[Opcode2];
	p++;
	}
else if(Opcode == 0x11)
	{
	Op = OpcodeTable[Opcode2];
	p++;
	}
else
	Op = OpcodeTable[Opcode];
switch(GetAddrMode(Opcode,OpRead(p)))
	{
	case c6809_addr_none:
	case c6809_addr_implied:
		sprintf(dest,"($%02X)\t%s",Opcode,Op);
		break;
	case c6809_addr_immediate:
		sprintf(dest,"($%02X)\t%s\t#$%04X",Opcode,Op,ReadWord(p));
		p += 2;
		break;
	case c6809_addr_immediate8:
		sprintf(dest,"($%02X)\t%s\t#$%02X",Opcode,Op,Read(p));
		p += 1;
		break;
	case c6809_addr_direct:
		sprintf(dest,"($%02X)\t%s\t<$%02X ($%04X)",Opcode,Op,Read(p),Read(p) | (DP << 8));
		p += 1;
		break;
	case c6809_addr_indexed:
		N = Read(p++);
		Reg = RegList[(N >> 5) & 3];
		if((N & 0x80) == 0)
			{
			if((N & 0x10) == 0)
				sprintf(dest,"($%02X)\t%s\t$%X,%c",Opcode,Op,N & 0xF,Reg);
			else
				sprintf(dest,"($%02X)\t%s\t-$%X,%c",Opcode,Op,N & 0xF,Reg);
			}
		else
			{
			char FF[2] = "";
			char FB[2] = "";
			
			if(N & 0x10)
				{
				strcpy(FF,"[");
				strcpy(FB,"]");
				}
			switch(N & 0xF)
				{
				case 0:	sprintf(dest,"($%02X)\t%s\t%s,%c+%s",Opcode,Op,FF,Reg,FB);	break;
				case 1:	sprintf(dest,"($%02X)\t%s\t%s,%c++%s",Opcode,Op,FF,Reg,FB);	break;
				case 2:	sprintf(dest,"($%02X)\t%s\t%s,-%c%s",Opcode,Op,FF,Reg,FB);	break;
				case 3:	sprintf(dest,"($%02X)\t%s\t%s,--%c%s",Opcode,Op,FF,Reg,FB);	break;
				case 4:	sprintf(dest,"($%02X)\t%s\t%s,%c%s",Opcode,Op,FF,Reg,FB);	break;
				case 5:	sprintf(dest,"($%02X)\t%s\t%sB,%c%s",Opcode,Op,FF,Reg,FB);	break;
				case 6:	sprintf(dest,"($%02X)\t%s\t%sA,%c%s",Opcode,Op,FF,Reg,FB);	break;
				case 8:	sprintf(dest,"($%02X)\t%s\t%s<$%02X,%c%s",Opcode,Op,FF,Read(p++),Reg,FB); break;
				case 9:	sprintf(dest,"($%02X)\t%s\t%s>$%04X,%c%s",Opcode,Op,FF,ReadWord(p),Reg,FB); p += 2; break;
				case 11:	sprintf(dest,"($%02X)\t%s\t%sD,%c%s",Opcode,Op,FF,Reg,FB);	break;
				case 12:	sprintf(dest,"($%02X)\t%s\t%s<$%02X,PC%s",Opcode,Op,FF,Read(p++),FB); break;
				case 13:	sprintf(dest,"($%02X)\t%s\t%s>$%04X,PC%s",Opcode,Op,FF,ReadWord(p),FB); p += 2; break;
				case 15:	sprintf(dest,"($%02X)\t%s\t%s$%04X%s",Opcode,Op,FF,ReadWord(p),FB); p += 2; break;
				}
			}
		break;
	case c6809_addr_extended:
		sprintf(dest,"($%02X)\t%s\t[$%02X]",Opcode,Op,ReadWord(p));
		p += 2;
		break;
	case c6809_addr_relative:
		sprintf(dest,"($%02X)\t%s\t$%04X",Opcode,Op,p + (s8)(Read(p) + 1));
		p += 1;
		break;
	case c6809_addr_relative16:
		sprintf(dest,"($%02X)\t%s\t$%04X",Opcode,Op,p + (s16)(ReadWord(p) + 1));
		p += 2;
		break;
	}
return(p);
}
